1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  package com.sun.java.util.jar.pack;
27  
28  import com.sun.java.util.jar.pack.ConstantPool.ClassEntry;
29  import com.sun.java.util.jar.pack.ConstantPool.DescriptorEntry;
30  import com.sun.java.util.jar.pack.ConstantPool.Entry;
31  import com.sun.java.util.jar.pack.ConstantPool.Index;
32  import com.sun.java.util.jar.pack.ConstantPool.MemberEntry;
33  import com.sun.java.util.jar.pack.ConstantPool.SignatureEntry;
34  import com.sun.java.util.jar.pack.ConstantPool.Utf8Entry;
35  import com.sun.java.util.jar.pack.Package.Class;
36  import com.sun.java.util.jar.pack.Package.File;
37  import com.sun.java.util.jar.pack.Package.InnerClass;
38  import java.io.ByteArrayOutputStream;
39  import java.io.EOFException;
40  import java.io.PrintStream;
41  import java.io.FilterInputStream;
42  import java.io.BufferedInputStream;
43  import java.io.InputStream;
44  import java.io.IOException;
45  import java.util.ArrayList;
46  import java.util.Map;
47  import java.util.Arrays;
48  import java.util.Collection;
49  import java.util.Comparator;
50  import java.util.HashSet;
51  import java.util.HashMap;
52  import java.util.Iterator;
53  import java.util.List;
54  import java.util.ListIterator;
55  import java.util.Set;
56  import static com.sun.java.util.jar.pack.Constants.*;
57  
58  
59  
60  
61  
62  
63  
64  class PackageReader extends BandStructure {
65      Package pkg;
66      byte[] bytes;
67      LimitedBuffer in;
68  
69      PackageReader(Package pkg, InputStream in) throws IOException {
70          this.pkg = pkg;
71          this.in = new LimitedBuffer(in);
72      }
73  
74      
75  
76  
77  
78  
79  
80      static
81      class LimitedBuffer extends BufferedInputStream {
82          long served;     
83          int  servedPos;  
84          long limit;      
85          long buffered;
86          public boolean atLimit() {
87              boolean z = (getBytesServed() == limit);
88              assert(!z || limit == buffered);
89              return z;
90          }
91          public long getBytesServed() {
92              return served + (pos - servedPos);
93          }
94          public void setReadLimit(long newLimit) {
95              if (newLimit == -1)
96                  limit = -1;
97              else
98                  limit = getBytesServed() + newLimit;
99          }
100         public long getReadLimit() {
101             if (limit == -1)
102                 return limit;
103             else
104                 return limit - getBytesServed();
105         }
106         public int read() throws IOException {
107             if (pos < count) {
108                 
109                 return buf[pos++] & 0xFF;
110             }
111             served += (pos - servedPos);
112             int ch = super.read();
113             servedPos = pos;
114             if (ch >= 0)  served += 1;
115             assert(served <= limit || limit == -1);
116             return ch;
117         }
118         public int read(byte b[], int off, int len) throws IOException {
119             served += (pos - servedPos);
120             int nr = super.read(b, off, len);
121             servedPos = pos;
122             if (nr >= 0)  served += nr;
123             assert(served <= limit || limit == -1);
124             return nr;
125         }
126         public long skip(long n) throws IOException {
127             throw new RuntimeException("no skipping");
128         }
129         LimitedBuffer(InputStream originalIn) {
130             super(null, 1<<14);
131             servedPos = pos;
132             super.in = new FilterInputStream(originalIn) {
133                 public int read() throws IOException {
134                     if (buffered == limit)
135                         return -1;
136                     ++buffered;
137                     return super.read();
138                 }
139                 public int read(byte b[], int off, int len) throws IOException {
140                     if (buffered == limit)
141                         return -1;
142                     if (limit != -1) {
143                         long remaining = limit - buffered;
144                         if (len > remaining)
145                             len = (int)remaining;
146                     }
147                     int nr = super.read(b, off, len);
148                     if (nr >= 0)  buffered += nr;
149                     return nr;
150                 }
151             };
152         }
153     }
154 
155     void read() throws IOException {
156         boolean ok = false;
157         try {
158             
159             
160             
161             
162             
163             
164             
165             
166             
167             readFileHeader();
168             readBandHeaders();
169             readConstantPool();  
170             readAttrDefs();
171             readInnerClasses();
172             Class[] classes = readClasses();
173             readByteCodes();
174             readFiles();     
175             assert(archiveSize1 == 0 || in.atLimit());
176             assert(archiveSize1 == 0 ||
177                    in.getBytesServed() == archiveSize0+archiveSize1);
178             all_bands.doneDisbursing();
179 
180             
181             for (int i = 0; i < classes.length; i++) {
182                 reconstructClass(classes[i]);
183             }
184 
185             ok = true;
186         } catch (Exception ee) {
187             Utils.log.warning("Error on input: "+ee, ee);
188             if (verbose > 0)
189                 Utils.log.info("Stream offsets:"+
190                                  " served="+in.getBytesServed()+
191                                  " buffered="+in.buffered+
192                                  " limit="+in.limit);
193             
194             if (ee instanceof IOException)  throw (IOException)ee;
195             if (ee instanceof RuntimeException)  throw (RuntimeException)ee;
196             throw new Error("error unpacking", ee);
197         }
198     }
199 
200     
201     int[] tagCount = new int[CONSTANT_Limit];
202     int numFiles;
203     int numAttrDefs;
204     int numInnerClasses;
205     int numClasses;
206 
207     void readFileHeader() throws IOException {
208         
209         
210         readArchiveMagic();
211         readArchiveHeader();
212     }
213 
214     
215     
216     private int getMagicInt32() throws IOException {
217         int res = 0;
218         for (int i = 0; i < 4; i++) {
219             res <<= 8;
220             res |= (archive_magic.getByte() & 0xFF);
221         }
222         return res;
223     }
224 
225     final static int MAGIC_BYTES = 4;
226 
227     void readArchiveMagic() throws IOException {
228 
229         
230         in.setReadLimit(MAGIC_BYTES + AH_LENGTH_MIN);
231 
232         
233         
234         archive_magic.expectLength(MAGIC_BYTES);
235         archive_magic.readFrom(in);
236 
237         
238         pkg.magic = getMagicInt32();
239         archive_magic.doneDisbursing();
240     }
241 
242     void readArchiveHeader() throws IOException {
243         
244         
245         
246         
247         
248         
249         
250         
251         
252         
253         
254         
255         
256         
257         
258         
259         
260         
261         
262         
263         
264         
265         
266         
267         
268         
269         assert(AH_LENGTH == 8+(ConstantPool.TAGS_IN_ORDER.length)+6);
270         archive_header_0.expectLength(AH_LENGTH_0);
271         archive_header_0.readFrom(in);
272 
273         pkg.package_minver = archive_header_0.getInt();
274         pkg.package_majver = archive_header_0.getInt();
275         pkg.checkVersion();
276         this.initPackageMajver(pkg.package_majver);
277 
278         archiveOptions = archive_header_0.getInt();
279         archive_header_0.doneDisbursing();
280 
281         
282         boolean haveSpecial = testBit(archiveOptions, AO_HAVE_SPECIAL_FORMATS);
283         boolean haveFiles   = testBit(archiveOptions, AO_HAVE_FILE_HEADERS);
284         boolean haveNumbers = testBit(archiveOptions, AO_HAVE_CP_NUMBERS);
285         initAttrIndexLimit();
286 
287         
288         archive_header_S.expectLength(haveFiles? AH_LENGTH_S: 0);
289         archive_header_S.readFrom(in);
290         if (haveFiles) {
291             long sizeHi = archive_header_S.getInt();
292             long sizeLo = archive_header_S.getInt();
293             archiveSize1 = (sizeHi << 32) + ((sizeLo << 32) >>> 32);
294             
295             in.setReadLimit(archiveSize1);  
296         } else {
297             archiveSize1 = 0;
298             in.setReadLimit(-1);  
299         }
300         archive_header_S.doneDisbursing();
301         archiveSize0 = in.getBytesServed();
302 
303         int remainingHeaders = AH_LENGTH - AH_LENGTH_0 - AH_LENGTH_S;
304         if (!haveFiles)    remainingHeaders -= AH_FILE_HEADER_LEN-AH_LENGTH_S;
305         if (!haveSpecial)  remainingHeaders -= AH_SPECIAL_FORMAT_LEN;
306         if (!haveNumbers)  remainingHeaders -= AH_CP_NUMBER_LEN;
307         assert(remainingHeaders >= AH_LENGTH_MIN - AH_LENGTH_0);
308         archive_header_1.expectLength(remainingHeaders);
309         archive_header_1.readFrom(in);
310 
311         if (haveFiles) {
312             archiveNextCount = archive_header_1.getInt();
313             pkg.default_modtime = archive_header_1.getInt();
314             numFiles = archive_header_1.getInt();
315         } else {
316             archiveNextCount = 0;
317             numFiles = 0;
318         }
319 
320         if (haveSpecial) {
321             band_headers.expectLength(archive_header_1.getInt());
322             numAttrDefs = archive_header_1.getInt();
323         } else {
324             band_headers.expectLength(0);
325             numAttrDefs = 0;
326         }
327 
328         readConstantPoolCounts(haveNumbers);
329 
330         numInnerClasses = archive_header_1.getInt();
331 
332         pkg.default_class_minver = (short) archive_header_1.getInt();
333         pkg.default_class_majver = (short) archive_header_1.getInt();
334         numClasses = archive_header_1.getInt();
335 
336         archive_header_1.doneDisbursing();
337 
338         
339         if (testBit(archiveOptions, AO_DEFLATE_HINT)) {
340             pkg.default_options |= FO_DEFLATE_HINT;
341         }
342     }
343 
344     void readBandHeaders() throws IOException {
345         band_headers.readFrom(in);
346         bandHeaderBytePos = 1;  
347         bandHeaderBytes = new byte[bandHeaderBytePos + band_headers.length()];
348         for (int i = bandHeaderBytePos; i < bandHeaderBytes.length; i++) {
349             bandHeaderBytes[i] = (byte) band_headers.getByte();
350         }
351         band_headers.doneDisbursing();
352     }
353 
354     void readConstantPoolCounts(boolean haveNumbers) throws IOException {
355         
356         for (int k = 0; k < ConstantPool.TAGS_IN_ORDER.length; k++) {
357             
358             
359             
360             
361             
362             
363             
364             
365             
366             
367             
368             
369             
370             
371             
372             
373             
374             byte tag = ConstantPool.TAGS_IN_ORDER[k];
375             if (!haveNumbers) {
376                 
377                 switch (tag) {
378                 case CONSTANT_Integer:
379                 case CONSTANT_Float:
380                 case CONSTANT_Long:
381                 case CONSTANT_Double:
382                     continue;
383                 }
384             }
385             tagCount[tag] = archive_header_1.getInt();
386         }
387     }
388 
389     protected Index getCPIndex(byte tag) {
390         return pkg.cp.getIndexByTag(tag);
391     }
392     Index initCPIndex(byte tag, Entry[] cpMap) {
393         if (verbose > 3) {
394             for (int i = 0; i < cpMap.length; i++) {
395                 Utils.log.fine("cp.add "+cpMap[i]);
396             }
397         }
398         Index index = ConstantPool.makeIndex(ConstantPool.tagName(tag), cpMap);
399         if (verbose > 1)  Utils.log.fine("Read "+index);
400         pkg.cp.initIndexByTag(tag, index);
401         return index;
402     }
403 
404     void readConstantPool() throws IOException {
405         
406         
407         
408         
409         
410         
411         
412         
413         
414         
415         
416         
417         
418 
419         if (verbose > 0)  Utils.log.info("Reading CP");
420 
421         for (int k = 0; k < ConstantPool.TAGS_IN_ORDER.length; k++) {
422             byte tag = ConstantPool.TAGS_IN_ORDER[k];
423             int  len = tagCount[tag];
424 
425             Entry[] cpMap = new Entry[len];
426             if (verbose > 0)
427                 Utils.log.info("Reading "+cpMap.length+" "+ConstantPool.tagName(tag)+" entries...");
428 
429             switch (tag) {
430             case CONSTANT_Utf8:
431                 readUtf8Bands(cpMap);
432                 break;
433             case CONSTANT_Integer:
434                 cp_Int.expectLength(cpMap.length);
435                 cp_Int.readFrom(in);
436                 for (int i = 0; i < cpMap.length; i++) {
437                     int x = cp_Int.getInt();  
438                     cpMap[i] = ConstantPool.getLiteralEntry(x);
439                 }
440                 cp_Int.doneDisbursing();
441                 break;
442             case CONSTANT_Float:
443                 cp_Float.expectLength(cpMap.length);
444                 cp_Float.readFrom(in);
445                 for (int i = 0; i < cpMap.length; i++) {
446                     int x = cp_Float.getInt();
447                     float fx = Float.intBitsToFloat(x);
448                     cpMap[i] = ConstantPool.getLiteralEntry(fx);
449                 }
450                 cp_Float.doneDisbursing();
451                 break;
452             case CONSTANT_Long:
453                 
454                 
455                 
456                 cp_Long_hi.expectLength(cpMap.length);
457                 cp_Long_hi.readFrom(in);
458                 cp_Long_lo.expectLength(cpMap.length);
459                 cp_Long_lo.readFrom(in);
460                 for (int i = 0; i < cpMap.length; i++) {
461                     long hi = cp_Long_hi.getInt();
462                     long lo = cp_Long_lo.getInt();
463                     long x = (hi << 32) + ((lo << 32) >>> 32);
464                     cpMap[i] = ConstantPool.getLiteralEntry(x);
465                 }
466                 cp_Long_hi.doneDisbursing();
467                 cp_Long_lo.doneDisbursing();
468                 break;
469             case CONSTANT_Double:
470                 
471                 
472                 
473                 cp_Double_hi.expectLength(cpMap.length);
474                 cp_Double_hi.readFrom(in);
475                 cp_Double_lo.expectLength(cpMap.length);
476                 cp_Double_lo.readFrom(in);
477                 for (int i = 0; i < cpMap.length; i++) {
478                     long hi = cp_Double_hi.getInt();
479                     long lo = cp_Double_lo.getInt();
480                     long x = (hi << 32) + ((lo << 32) >>> 32);
481                     double dx = Double.longBitsToDouble(x);
482                     cpMap[i] = ConstantPool.getLiteralEntry(dx);
483                 }
484                 cp_Double_hi.doneDisbursing();
485                 cp_Double_lo.doneDisbursing();
486                 break;
487             case CONSTANT_String:
488                 cp_String.expectLength(cpMap.length);
489                 cp_String.readFrom(in);
490                 cp_String.setIndex(getCPIndex(CONSTANT_Utf8));
491                 for (int i = 0; i < cpMap.length; i++) {
492                     cpMap[i] = ConstantPool.getLiteralEntry(cp_String.getRef().stringValue());
493                 }
494                 cp_String.doneDisbursing();
495                 break;
496             case CONSTANT_Class:
497                 cp_Class.expectLength(cpMap.length);
498                 cp_Class.readFrom(in);
499                 cp_Class.setIndex(getCPIndex(CONSTANT_Utf8));
500                 for (int i = 0; i < cpMap.length; i++) {
501                     cpMap[i] = ConstantPool.getClassEntry(cp_Class.getRef().stringValue());
502                 }
503                 cp_Class.doneDisbursing();
504                 break;
505             case CONSTANT_Signature:
506                 readSignatureBands(cpMap);
507                 break;
508             case CONSTANT_NameandType:
509                 
510                 
511                 
512                 cp_Descr_name.expectLength(cpMap.length);
513                 cp_Descr_name.readFrom(in);
514                 cp_Descr_name.setIndex(getCPIndex(CONSTANT_Utf8));
515                 cp_Descr_type.expectLength(cpMap.length);
516                 cp_Descr_type.readFrom(in);
517                 cp_Descr_type.setIndex(getCPIndex(CONSTANT_Signature));
518                 for (int i = 0; i < cpMap.length; i++) {
519                     Entry ref  = cp_Descr_name.getRef();
520                     Entry ref2 = cp_Descr_type.getRef();
521                     cpMap[i] = ConstantPool.getDescriptorEntry((Utf8Entry)ref,
522                                                         (SignatureEntry)ref2);
523                 }
524                 cp_Descr_name.doneDisbursing();
525                 cp_Descr_type.doneDisbursing();
526                 break;
527             case CONSTANT_Fieldref:
528                 readMemberRefs(tag, cpMap, cp_Field_class, cp_Field_desc);
529                 break;
530             case CONSTANT_Methodref:
531                 readMemberRefs(tag, cpMap, cp_Method_class, cp_Method_desc);
532                 break;
533             case CONSTANT_InterfaceMethodref:
534                 readMemberRefs(tag, cpMap, cp_Imethod_class, cp_Imethod_desc);
535                 break;
536             default:
537                 assert(false);
538             }
539 
540             Index index = initCPIndex(tag, cpMap);
541 
542             if (optDumpBands) {
543                 try (PrintStream ps = new PrintStream(getDumpStream(index, ".idx"))) {
544                     printArrayTo(ps, index.cpMap, 0, index.cpMap.length);
545                 }
546             }
547         }
548 
549         cp_bands.doneDisbursing();
550 
551         setBandIndexes();
552     }
553 
554     void readUtf8Bands(Entry[] cpMap) throws IOException {
555         
556         
557         
558         
559         
560         
561         
562         int len = cpMap.length;
563         if (len == 0)
564             return;  
565 
566         
567         final int SUFFIX_SKIP_1 = 1;
568         final int PREFIX_SKIP_2 = 2;
569 
570         
571         cp_Utf8_prefix.expectLength(Math.max(0, len - PREFIX_SKIP_2));
572         cp_Utf8_prefix.readFrom(in);
573 
574         
575         cp_Utf8_suffix.expectLength(Math.max(0, len - SUFFIX_SKIP_1));
576         cp_Utf8_suffix.readFrom(in);
577 
578         char[][] suffixChars = new char[len][];
579         int bigSuffixCount = 0;
580 
581         
582         cp_Utf8_chars.expectLength(cp_Utf8_suffix.getIntTotal());
583         cp_Utf8_chars.readFrom(in);
584         for (int i = 0; i < len; i++) {
585             int suffix = (i < SUFFIX_SKIP_1)? 0: cp_Utf8_suffix.getInt();
586             if (suffix == 0 && i >= SUFFIX_SKIP_1) {
587                 
588                 bigSuffixCount += 1;
589                 continue;
590             }
591             suffixChars[i] = new char[suffix];
592             for (int j = 0; j < suffix; j++) {
593                 int ch = cp_Utf8_chars.getInt();
594                 assert(ch == (char)ch);
595                 suffixChars[i][j] = (char)ch;
596             }
597         }
598         cp_Utf8_chars.doneDisbursing();
599 
600         
601         int maxChars = 0;
602         cp_Utf8_big_suffix.expectLength(bigSuffixCount);
603         cp_Utf8_big_suffix.readFrom(in);
604         cp_Utf8_suffix.resetForSecondPass();
605         for (int i = 0; i < len; i++) {
606             int suffix = (i < SUFFIX_SKIP_1)? 0: cp_Utf8_suffix.getInt();
607             int prefix = (i < PREFIX_SKIP_2)? 0: cp_Utf8_prefix.getInt();
608             if (suffix == 0 && i >= SUFFIX_SKIP_1) {
609                 assert(suffixChars[i] == null);
610                 suffix = cp_Utf8_big_suffix.getInt();
611             } else {
612                 assert(suffixChars[i] != null);
613             }
614             if (maxChars < prefix + suffix)
615                 maxChars = prefix + suffix;
616         }
617         char[] buf = new char[maxChars];
618 
619         
620         cp_Utf8_suffix.resetForSecondPass();
621         cp_Utf8_big_suffix.resetForSecondPass();
622         for (int i = 0; i < len; i++) {
623             if (i < SUFFIX_SKIP_1)  continue;
624             int suffix = cp_Utf8_suffix.getInt();
625             if (suffix != 0)  continue;  
626             suffix = cp_Utf8_big_suffix.getInt();
627             suffixChars[i] = new char[suffix];
628             if (suffix == 0) {
629                 
630                 continue;
631             }
632             IntBand packed = cp_Utf8_big_chars.newIntBand("(Utf8_big_"+i+")");
633             packed.expectLength(suffix);
634             packed.readFrom(in);
635             for (int j = 0; j < suffix; j++) {
636                 int ch = packed.getInt();
637                 assert(ch == (char)ch);
638                 suffixChars[i][j] = (char)ch;
639             }
640             packed.doneDisbursing();
641         }
642         cp_Utf8_big_chars.doneDisbursing();
643 
644         
645         cp_Utf8_prefix.resetForSecondPass();
646         cp_Utf8_suffix.resetForSecondPass();
647         cp_Utf8_big_suffix.resetForSecondPass();
648         for (int i = 0; i < len; i++) {
649             int prefix = (i < PREFIX_SKIP_2)? 0: cp_Utf8_prefix.getInt();
650             int suffix = (i < SUFFIX_SKIP_1)? 0: cp_Utf8_suffix.getInt();
651             if (suffix == 0 && i >= SUFFIX_SKIP_1)
652                 suffix = cp_Utf8_big_suffix.getInt();
653 
654             
655             System.arraycopy(suffixChars[i], 0, buf, prefix, suffix);
656 
657             cpMap[i] = ConstantPool.getUtf8Entry(new String(buf, 0, prefix+suffix));
658         }
659 
660         cp_Utf8_prefix.doneDisbursing();
661         cp_Utf8_suffix.doneDisbursing();
662         cp_Utf8_big_suffix.doneDisbursing();
663     }
664 
665     Map<Utf8Entry, SignatureEntry> utf8Signatures;
666 
667     void readSignatureBands(Entry[] cpMap) throws IOException {
668         
669         
670         
671         cp_Signature_form.expectLength(cpMap.length);
672         cp_Signature_form.readFrom(in);
673         cp_Signature_form.setIndex(getCPIndex(CONSTANT_Utf8));
674         int[] numSigClasses = new int[cpMap.length];
675         for (int i = 0; i < cpMap.length; i++) {
676             Utf8Entry formRef = (Utf8Entry) cp_Signature_form.getRef();
677             numSigClasses[i] = ConstantPool.countClassParts(formRef);
678         }
679         cp_Signature_form.resetForSecondPass();
680         cp_Signature_classes.expectLength(getIntTotal(numSigClasses));
681         cp_Signature_classes.readFrom(in);
682         cp_Signature_classes.setIndex(getCPIndex(CONSTANT_Class));
683         utf8Signatures = new HashMap<>();
684         for (int i = 0; i < cpMap.length; i++) {
685             Utf8Entry formRef = (Utf8Entry) cp_Signature_form.getRef();
686             ClassEntry[] classRefs = new ClassEntry[numSigClasses[i]];
687             for (int j = 0; j < classRefs.length; j++) {
688                 classRefs[j] = (ClassEntry) cp_Signature_classes.getRef();
689             }
690             SignatureEntry se = ConstantPool.getSignatureEntry(formRef, classRefs);
691             cpMap[i] = se;
692             utf8Signatures.put(se.asUtf8Entry(), se);
693         }
694         cp_Signature_form.doneDisbursing();
695         cp_Signature_classes.doneDisbursing();
696     }
697 
698     void readMemberRefs(byte tag, Entry[] cpMap, CPRefBand cp_class, CPRefBand cp_desc) throws IOException {
699         
700         
701         
702         
703         
704         
705         
706         
707         
708         cp_class.expectLength(cpMap.length);
709         cp_class.readFrom(in);
710         cp_class.setIndex(getCPIndex(CONSTANT_Class));
711         cp_desc.expectLength(cpMap.length);
712         cp_desc.readFrom(in);
713         cp_desc.setIndex(getCPIndex(CONSTANT_NameandType));
714         for (int i = 0; i < cpMap.length; i++) {
715             ClassEntry      mclass = (ClassEntry     ) cp_class.getRef();
716             DescriptorEntry mdescr = (DescriptorEntry) cp_desc.getRef();
717             cpMap[i] = ConstantPool.getMemberEntry(tag, mclass, mdescr);
718         }
719         cp_class.doneDisbursing();
720         cp_desc.doneDisbursing();
721     }
722 
723     void readFiles() throws IOException {
724         
725         
726         
727         
728         
729         
730         
731         if (verbose > 0)
732             Utils.log.info("  ...building "+numFiles+" files...");
733         file_name.expectLength(numFiles);
734         file_size_lo.expectLength(numFiles);
735         int options = archiveOptions;
736         boolean haveSizeHi  = testBit(options, AO_HAVE_FILE_SIZE_HI);
737         boolean haveModtime = testBit(options, AO_HAVE_FILE_MODTIME);
738         boolean haveOptions = testBit(options, AO_HAVE_FILE_OPTIONS);
739         if (haveSizeHi)
740             file_size_hi.expectLength(numFiles);
741         if (haveModtime)
742             file_modtime.expectLength(numFiles);
743         if (haveOptions)
744             file_options.expectLength(numFiles);
745 
746         file_name.readFrom(in);
747         file_size_hi.readFrom(in);
748         file_size_lo.readFrom(in);
749         file_modtime.readFrom(in);
750         file_options.readFrom(in);
751         file_bits.setInputStreamFrom(in);
752 
753         Iterator nextClass = pkg.getClasses().iterator();
754 
755         
756         long totalFileLength = 0;
757         long[] fileLengths = new long[numFiles];
758         for (int i = 0; i < numFiles; i++) {
759             long size = ((long)file_size_lo.getInt() << 32) >>> 32;
760             if (haveSizeHi)
761                 size += (long)file_size_hi.getInt() << 32;
762             fileLengths[i] = size;
763             totalFileLength += size;
764         }
765         assert(in.getReadLimit() == -1 || in.getReadLimit() == totalFileLength);
766 
767         byte[] buf = new byte[1<<16];
768         for (int i = 0; i < numFiles; i++) {
769             
770             Utf8Entry name = (Utf8Entry) file_name.getRef();
771             long size = fileLengths[i];
772             File file = pkg.new File(name);
773             file.modtime = pkg.default_modtime;
774             file.options = pkg.default_options;
775             if (haveModtime)
776                 file.modtime += file_modtime.getInt();
777             if (haveOptions)
778                 file.options |= file_options.getInt();
779             if (verbose > 1)
780                 Utils.log.fine("Reading "+size+" bytes of "+name.stringValue());
781             long toRead = size;
782             while (toRead > 0) {
783                 int nr = buf.length;
784                 if (nr > toRead)  nr = (int) toRead;
785                 nr = file_bits.getInputStream().read(buf, 0, nr);
786                 if (nr < 0)  throw new EOFException();
787                 file.addBytes(buf, 0, nr);
788                 toRead -= nr;
789             }
790             pkg.addFile(file);
791             if (file.isClassStub()) {
792                 assert(file.getFileLength() == 0);
793                 Class cls = (Class) nextClass.next();
794                 cls.initFile(file);
795             }
796         }
797 
798         
799         while (nextClass.hasNext()) {
800             Class cls = (Class) nextClass.next();
801             cls.initFile(null);  
802             cls.file.modtime = pkg.default_modtime;
803         }
804 
805         file_name.doneDisbursing();
806         file_size_hi.doneDisbursing();
807         file_size_lo.doneDisbursing();
808         file_modtime.doneDisbursing();
809         file_options.doneDisbursing();
810         file_bits.doneDisbursing();
811         file_bands.doneDisbursing();
812 
813         if (archiveSize1 != 0 && !in.atLimit()) {
814             throw new RuntimeException("Predicted archive_size "+
815                                        archiveSize1+" != "+
816                                        (in.getBytesServed()-archiveSize0));
817         }
818     }
819 
820     void readAttrDefs() throws IOException {
821         
822         
823         
824         
825         attr_definition_headers.expectLength(numAttrDefs);
826         attr_definition_name.expectLength(numAttrDefs);
827         attr_definition_layout.expectLength(numAttrDefs);
828         attr_definition_headers.readFrom(in);
829         attr_definition_name.readFrom(in);
830         attr_definition_layout.readFrom(in);
831         try (PrintStream dump = !optDumpBands ? null
832                  : new PrintStream(getDumpStream(attr_definition_headers, ".def")))
833         {
834             for (int i = 0; i < numAttrDefs; i++) {
835                 int       header = attr_definition_headers.getByte();
836                 Utf8Entry name   = (Utf8Entry) attr_definition_name.getRef();
837                 Utf8Entry layout = (Utf8Entry) attr_definition_layout.getRef();
838                 int       ctype  = (header &  ADH_CONTEXT_MASK);
839                 int       index  = (header >> ADH_BIT_SHIFT) - ADH_BIT_IS_LSB;
840                 Attribute.Layout def = new Attribute.Layout(ctype,
841                                                             name.stringValue(),
842                                                             layout.stringValue());
843                 
844                 String pvLayout = def.layoutForPackageMajver(getPackageMajver());
845                 if (!pvLayout.equals(def.layout())) {
846                     throw new IOException("Bad attribute layout in version 150 archive: "+def.layout());
847                 }
848                 this.setAttributeLayoutIndex(def, index);
849                 if (dump != null)  dump.println(index+" "+def);
850             }
851         }
852         attr_definition_headers.doneDisbursing();
853         attr_definition_name.doneDisbursing();
854         attr_definition_layout.doneDisbursing();
855         
856         
857         makeNewAttributeBands();
858         attr_definition_bands.doneDisbursing();
859     }
860 
861     void readInnerClasses() throws IOException {
862         
863         
864         
865         
866         
867         ic_this_class.expectLength(numInnerClasses);
868         ic_this_class.readFrom(in);
869         ic_flags.expectLength(numInnerClasses);
870         ic_flags.readFrom(in);
871         int longICCount = 0;
872         for (int i = 0; i < numInnerClasses; i++) {
873             int flags = ic_flags.getInt();
874             boolean longForm = (flags & ACC_IC_LONG_FORM) != 0;
875             if (longForm) {
876                 longICCount += 1;
877             }
878         }
879         ic_outer_class.expectLength(longICCount);
880         ic_outer_class.readFrom(in);
881         ic_name.expectLength(longICCount);
882         ic_name.readFrom(in);
883         ic_flags.resetForSecondPass();
884         List<InnerClass> icList = new ArrayList<>(numInnerClasses);
885         for (int i = 0; i < numInnerClasses; i++) {
886             int flags = ic_flags.getInt();
887             boolean longForm = (flags & ACC_IC_LONG_FORM) != 0;
888             flags &= ~ACC_IC_LONG_FORM;
889             ClassEntry thisClass = (ClassEntry) ic_this_class.getRef();
890             ClassEntry outerClass;
891             Utf8Entry  thisName;
892             if (longForm) {
893                 outerClass = (ClassEntry) ic_outer_class.getRef();
894                 thisName   = (Utf8Entry)  ic_name.getRef();
895             } else {
896                 String n = thisClass.stringValue();
897                 String[] parse = Package.parseInnerClassName(n);
898                 assert(parse != null);
899                 String pkgOuter = parse[0];
900                 
901                 String name     = parse[2];
902                 if (pkgOuter == null)
903                     outerClass = null;
904                 else
905                     outerClass = ConstantPool.getClassEntry(pkgOuter);
906                 if (name == null)
907                     thisName   = null;
908                 else
909                     thisName   = ConstantPool.getUtf8Entry(name);
910             }
911             InnerClass ic =
912                 new InnerClass(thisClass, outerClass, thisName, flags);
913             assert(longForm || ic.predictable);
914             icList.add(ic);
915         }
916         ic_flags.doneDisbursing();
917         ic_this_class.doneDisbursing();
918         ic_outer_class.doneDisbursing();
919         ic_name.doneDisbursing();
920         pkg.setAllInnerClasses(icList);
921         ic_bands.doneDisbursing();
922     }
923 
924     void readLocalInnerClasses(Class cls) throws IOException {
925         int nc = class_InnerClasses_N.getInt();
926         List<InnerClass> localICs = new ArrayList<>(nc);
927         for (int i = 0; i < nc; i++) {
928             ClassEntry thisClass = (ClassEntry) class_InnerClasses_RC.getRef();
929             int        flags     =              class_InnerClasses_F.getInt();
930             if (flags == 0) {
931                 
932                 InnerClass ic = pkg.getGlobalInnerClass(thisClass);
933                 assert(ic != null);  
934                 localICs.add(ic);
935             } else {
936                 if (flags == ACC_IC_LONG_FORM)
937                     flags = 0;  
938                 ClassEntry outer = (ClassEntry) class_InnerClasses_outer_RCN.getRef();
939                 Utf8Entry name   = (Utf8Entry)  class_InnerClasses_name_RUN.getRef();
940                 localICs.add(new InnerClass(thisClass, outer, name, flags));
941             }
942         }
943         cls.setInnerClasses(localICs);
944         
945         
946         
947         
948     }
949 
950     static final int NO_FLAGS_YET = 0;  
951 
952     Class[] readClasses() throws IOException {
953         
954         
955         
956         
957         
958         
959         
960         
961         Class[] classes = new Class[numClasses];
962         if (verbose > 0)
963             Utils.log.info("  ...building "+classes.length+" classes...");
964 
965         class_this.expectLength(numClasses);
966         class_super.expectLength(numClasses);
967         class_interface_count.expectLength(numClasses);
968 
969         class_this.readFrom(in);
970         class_super.readFrom(in);
971         class_interface_count.readFrom(in);
972         class_interface.expectLength(class_interface_count.getIntTotal());
973         class_interface.readFrom(in);
974         for (int i = 0; i < classes.length; i++) {
975             ClassEntry   thisClass  = (ClassEntry) class_this.getRef();
976             ClassEntry   superClass = (ClassEntry) class_super.getRef();
977             ClassEntry[] interfaces = new ClassEntry[class_interface_count.getInt()];
978             for (int j = 0; j < interfaces.length; j++) {
979                 interfaces[j] = (ClassEntry) class_interface.getRef();
980             }
981             
982             if (superClass == thisClass)  superClass = null;
983             Class cls = pkg.new Class(NO_FLAGS_YET,
984                                       thisClass, superClass, interfaces);
985             classes[i] = cls;
986         }
987         class_this.doneDisbursing();
988         class_super.doneDisbursing();
989         class_interface_count.doneDisbursing();
990         class_interface.doneDisbursing();
991         readMembers(classes);
992         countAndReadAttrs(ATTR_CONTEXT_CLASS, Arrays.asList(classes));
993         pkg.trimToSize();
994         readCodeHeaders();
995         
996         
997         return classes;
998     }
999 
1000     private int getOutputIndex(Entry e) {
1001         
1002         assert(e.tag != CONSTANT_Signature);
1003         int k = pkg.cp.untypedIndexOf(e);
1004         
1005         
1006         if (k >= 0)
1007             return k;
1008         if (e.tag == CONSTANT_Utf8) {
1009             Entry se = (Entry) utf8Signatures.get(e);
1010             return pkg.cp.untypedIndexOf(se);
1011         }
1012         return -1;
1013     }
1014 
1015     Comparator<Entry> entryOutputOrder = new Comparator<Entry>() {
1016         public int compare(Entry  e0, Entry e1) {
1017             int k0 = getOutputIndex(e0);
1018             int k1 = getOutputIndex(e1);
1019             if (k0 >= 0 && k1 >= 0)
1020                 
1021                 return k0 - k1;
1022             if (k0 == k1)
1023                 
1024                 return e0.compareTo(e1);
1025             
1026             return (k0 >= 0)? 0-1: 1-0;
1027         }
1028     };
1029 
1030     void reconstructClass(Class cls) {
1031         if (verbose > 1)  Utils.log.fine("reconstruct "+cls);
1032 
1033         
1034         Attribute retroVersion = cls.getAttribute(attrClassFileVersion);
1035         if (retroVersion != null) {
1036             cls.removeAttribute(retroVersion);
1037             short[] minmajver = parseClassFileVersionAttr(retroVersion);
1038             cls.minver = minmajver[0];
1039             cls.majver = minmajver[1];
1040         } else {
1041             cls.minver = pkg.default_class_minver;
1042             cls.majver = pkg.default_class_majver;
1043         }
1044 
1045         
1046         cls.expandSourceFile();
1047 
1048         
1049         cls.setCPMap(reconstructLocalCPMap(cls));
1050     }
1051 
1052     Entry[] reconstructLocalCPMap(Class cls) {
1053         Set<Entry> ldcRefs = ldcRefMap.get(cls);
1054         Set<Entry> cpRefs = new HashSet<>();
1055 
1056         
1057         cls.visitRefs(VRM_CLASSIC, cpRefs);
1058 
1059         
1060         ConstantPool.completeReferencesIn(cpRefs, true);
1061 
1062         
1063         
1064         int changed = cls.expandLocalICs();
1065 
1066         if (changed != 0) {
1067             if (changed > 0) {
1068                 
1069                 cls.visitInnerClassRefs(VRM_CLASSIC, cpRefs);
1070             } else {
1071                 
1072                 cpRefs.clear();
1073                 cls.visitRefs(VRM_CLASSIC, cpRefs);
1074             }
1075 
1076             
1077             ConstantPool.completeReferencesIn(cpRefs, true);
1078         }
1079 
1080         
1081         int numDoubles = 0;
1082         for (Entry e : cpRefs) {
1083             if (e.isDoubleWord())  numDoubles++;
1084             assert(e.tag != CONSTANT_Signature) : (e);
1085         }
1086         Entry[] cpMap = new Entry[1+numDoubles+cpRefs.size()];
1087         int fillp = 1;
1088 
1089         
1090         if (ldcRefs != null) {
1091             assert(cpRefs.containsAll(ldcRefs));
1092             for (Entry e : ldcRefs) {
1093                 cpMap[fillp++] = e;
1094             }
1095             assert(fillp == 1+ldcRefs.size());
1096             cpRefs.removeAll(ldcRefs);
1097             ldcRefs = null;  
1098         }
1099 
1100         
1101         Set<Entry> wideRefs = cpRefs;
1102         cpRefs = null;  
1103         int narrowLimit = fillp;
1104         for (Entry e : wideRefs) {
1105             cpMap[fillp++] = e;
1106         }
1107         assert(fillp == narrowLimit+wideRefs.size());
1108         Arrays.sort(cpMap, 1, narrowLimit, entryOutputOrder);
1109         Arrays.sort(cpMap, narrowLimit, fillp, entryOutputOrder);
1110 
1111         if (verbose > 3) {
1112             Utils.log.fine("CP of "+this+" {");
1113             for (int i = 0; i < fillp; i++) {
1114                 Entry e = cpMap[i];
1115                 Utils.log.fine("  "+((e==null)?-1:getOutputIndex(e))
1116                                    +" : "+e);
1117             }
1118             Utils.log.fine("}");
1119         }
1120 
1121         
1122         int revp = cpMap.length;
1123         for (int i = fillp; --i >= 1; ) {
1124             Entry e = cpMap[i];
1125             if (e.isDoubleWord())
1126                 cpMap[--revp] = null;
1127             cpMap[--revp] = e;
1128         }
1129         assert(revp == 1);  
1130 
1131         return cpMap;
1132     }
1133 
1134     void readMembers(Class[] classes) throws IOException {
1135         
1136         
1137         
1138         
1139         
1140         
1141         
1142         
1143         
1144         
1145         
1146         assert(classes.length == numClasses);
1147         class_field_count.expectLength(numClasses);
1148         class_method_count.expectLength(numClasses);
1149         class_field_count.readFrom(in);
1150         class_method_count.readFrom(in);
1151 
1152         
1153         int totalNF = class_field_count.getIntTotal();
1154         int totalNM = class_method_count.getIntTotal();
1155         field_descr.expectLength(totalNF);
1156         method_descr.expectLength(totalNM);
1157         if (verbose > 1)  Utils.log.fine("expecting #fields="+totalNF+" and #methods="+totalNM+" in #classes="+numClasses);
1158 
1159         List<Class.Field> fields = new ArrayList<>(totalNF);
1160         field_descr.readFrom(in);
1161         for (int i = 0; i < classes.length; i++) {
1162             Class c = classes[i];
1163             int nf = class_field_count.getInt();
1164             for (int j = 0; j < nf; j++) {
1165                 Class.Field f = c.new Field(NO_FLAGS_YET, (DescriptorEntry)
1166                                             field_descr.getRef());
1167                 fields.add(f);
1168             }
1169         }
1170         class_field_count.doneDisbursing();
1171         field_descr.doneDisbursing();
1172         countAndReadAttrs(ATTR_CONTEXT_FIELD, fields);
1173         fields = null;  
1174 
1175         List<Class.Method> methods = new ArrayList<>(totalNM);
1176         method_descr.readFrom(in);
1177         for (int i = 0; i < classes.length; i++) {
1178             Class c = classes[i];
1179             int nm = class_method_count.getInt();
1180             for (int j = 0; j < nm; j++) {
1181                 Class.Method m = c.new Method(NO_FLAGS_YET, (DescriptorEntry)
1182                                               method_descr.getRef());
1183                 methods.add(m);
1184             }
1185         }
1186         class_method_count.doneDisbursing();
1187         method_descr.doneDisbursing();
1188         countAndReadAttrs(ATTR_CONTEXT_METHOD, methods);
1189 
1190         
1191         
1192         
1193         allCodes = buildCodeAttrs(methods);
1194     }
1195 
1196     Code[] allCodes;
1197     List<Code> codesWithFlags;
1198     Map<Class, Set<Entry>> ldcRefMap = new HashMap<>();
1199 
1200     Code[] buildCodeAttrs(List<Class.Method> methods) {
1201         List<Code> codes = new ArrayList<>(methods.size());
1202         for (Class.Method m : methods) {
1203             if (m.getAttribute(attrCodeEmpty) != null) {
1204                 m.code = new Code(m);
1205                 codes.add(m.code);
1206             }
1207         }
1208         Code[] a = new Code[codes.size()];
1209         codes.toArray(a);
1210         return a;
1211     }
1212 
1213     void readCodeHeaders() throws IOException {
1214         
1215         
1216         
1217         
1218         
1219         
1220         
1221         
1222         boolean attrsOK = testBit(archiveOptions, AO_HAVE_ALL_CODE_FLAGS);
1223         code_headers.expectLength(allCodes.length);
1224         code_headers.readFrom(in);
1225         List<Code> longCodes = new ArrayList<>(allCodes.length / 10);
1226         for (int i = 0; i < allCodes.length; i++) {
1227             Code c = allCodes[i];
1228             int sc = code_headers.getByte();
1229             assert(sc == (sc & 0xFF));
1230             if (verbose > 2)
1231                 Utils.log.fine("codeHeader "+c+" = "+sc);
1232             if (sc == LONG_CODE_HEADER) {
1233                 
1234                 longCodes.add(c);
1235                 continue;
1236             }
1237             
1238             c.setMaxStack(     shortCodeHeader_max_stack(sc) );
1239             c.setMaxNALocals(  shortCodeHeader_max_na_locals(sc) );
1240             c.setHandlerCount( shortCodeHeader_handler_count(sc) );
1241             assert(shortCodeHeader(c) == sc);
1242         }
1243         code_headers.doneDisbursing();
1244         code_max_stack.expectLength(longCodes.size());
1245         code_max_na_locals.expectLength(longCodes.size());
1246         code_handler_count.expectLength(longCodes.size());
1247 
1248         
1249         code_max_stack.readFrom(in);
1250         code_max_na_locals.readFrom(in);
1251         code_handler_count.readFrom(in);
1252         for (Code c : longCodes) {
1253             c.setMaxStack(     code_max_stack.getInt() );
1254             c.setMaxNALocals(  code_max_na_locals.getInt() );
1255             c.setHandlerCount( code_handler_count.getInt() );
1256         }
1257         code_max_stack.doneDisbursing();
1258         code_max_na_locals.doneDisbursing();
1259         code_handler_count.doneDisbursing();
1260 
1261         readCodeHandlers();
1262 
1263         if (attrsOK) {
1264             
1265             codesWithFlags = Arrays.asList(allCodes);
1266         } else {
1267             
1268             codesWithFlags = longCodes;
1269         }
1270         countAttrs(ATTR_CONTEXT_CODE, codesWithFlags);
1271         
1272     }
1273 
1274     void readCodeHandlers() throws IOException {
1275         
1276         
1277         
1278         
1279         
1280         
1281         
1282         int nh = 0;
1283         for (int i = 0; i < allCodes.length; i++) {
1284             Code c = allCodes[i];
1285             nh += c.getHandlerCount();
1286         }
1287 
1288         ValueBand[] code_handler_bands = {
1289             code_handler_start_P,
1290             code_handler_end_PO,
1291             code_handler_catch_PO,
1292             code_handler_class_RCN
1293         };
1294 
1295         for (int i = 0; i < code_handler_bands.length; i++) {
1296             code_handler_bands[i].expectLength(nh);
1297             code_handler_bands[i].readFrom(in);
1298         }
1299 
1300         for (int i = 0; i < allCodes.length; i++) {
1301             Code c = allCodes[i];
1302             for (int j = 0, jmax = c.getHandlerCount(); j < jmax; j++) {
1303                 c.handler_class[j] = code_handler_class_RCN.getRef();
1304                 
1305                 
1306                 c.handler_start[j] = code_handler_start_P.getInt();
1307                 c.handler_end[j]   = code_handler_end_PO.getInt();
1308                 c.handler_catch[j] = code_handler_catch_PO.getInt();
1309             }
1310         }
1311         for (int i = 0; i < code_handler_bands.length; i++) {
1312             code_handler_bands[i].doneDisbursing();
1313         }
1314     }
1315 
1316     void fixupCodeHandlers() {
1317         
1318         for (int i = 0; i < allCodes.length; i++) {
1319             Code c = allCodes[i];
1320             for (int j = 0, jmax = c.getHandlerCount(); j < jmax; j++) {
1321                 int sum = c.handler_start[j];
1322                 c.handler_start[j] = c.decodeBCI(sum);
1323                 sum += c.handler_end[j];
1324                 c.handler_end[j]   = c.decodeBCI(sum);
1325                 sum += c.handler_catch[j];
1326                 c.handler_catch[j] = c.decodeBCI(sum);
1327             }
1328         }
1329     }
1330 
1331     
1332     
1333     
1334     
1335     void countAndReadAttrs(int ctype, Collection holders) throws IOException {
1336         
1337         
1338         
1339         
1340         
1341         
1342         
1343         
1344         
1345         
1346         
1347         
1348         
1349         
1350         
1351         
1352         
1353         
1354         
1355         
1356         
1357         
1358         
1359         
1360         
1361         
1362         
1363         
1364         
1365         
1366         
1367         
1368         
1369         
1370         
1371         
1372         
1373         
1374         
1375         
1376         
1377         
1378         
1379         
1380         
1381         
1382 
1383         countAttrs(ctype, holders);
1384         readAttrs(ctype, holders);
1385     }
1386 
1387     
1388     
1389     void countAttrs(int ctype, Collection holders) throws IOException {
1390         
1391         MultiBand xxx_attr_bands = attrBands[ctype];
1392         long flagMask = attrFlagMask[ctype];
1393         if (verbose > 1) {
1394             Utils.log.fine("scanning flags and attrs for "+Attribute.contextName(ctype)+"["+holders.size()+"]");
1395         }
1396 
1397         
1398         
1399         List<Attribute.Layout> defList = attrDefs.get(ctype);
1400         Attribute.Layout[] defs = new Attribute.Layout[defList.size()];
1401         defList.toArray(defs);
1402         IntBand xxx_flags_hi = getAttrBand(xxx_attr_bands, AB_FLAGS_HI);
1403         IntBand xxx_flags_lo = getAttrBand(xxx_attr_bands, AB_FLAGS_LO);
1404         IntBand xxx_attr_count = getAttrBand(xxx_attr_bands, AB_ATTR_COUNT);
1405         IntBand xxx_attr_indexes = getAttrBand(xxx_attr_bands, AB_ATTR_INDEXES);
1406         IntBand xxx_attr_calls = getAttrBand(xxx_attr_bands, AB_ATTR_CALLS);
1407 
1408         
1409         int overflowMask = attrOverflowMask[ctype];
1410         int overflowHolderCount = 0;
1411         boolean haveLongFlags = haveFlagsHi(ctype);
1412         xxx_flags_hi.expectLength(haveLongFlags? holders.size(): 0);
1413         xxx_flags_hi.readFrom(in);
1414         xxx_flags_lo.expectLength(holders.size());
1415         xxx_flags_lo.readFrom(in);
1416         assert((flagMask & overflowMask) == overflowMask);
1417         for (Iterator i = holders.iterator(); i.hasNext(); ) {
1418             Attribute.Holder h = (Attribute.Holder) i.next();
1419             int flags = xxx_flags_lo.getInt();
1420             h.flags = flags;
1421             if ((flags & overflowMask) != 0)
1422                 overflowHolderCount += 1;
1423         }
1424 
1425         
1426         xxx_attr_count.expectLength(overflowHolderCount);
1427         xxx_attr_count.readFrom(in);
1428         xxx_attr_indexes.expectLength(xxx_attr_count.getIntTotal());
1429         xxx_attr_indexes.readFrom(in);
1430 
1431         
1432         
1433         
1434         
1435         int[] totalCounts = new int[defs.length];
1436         for (Iterator i = holders.iterator(); i.hasNext(); ) {
1437             Attribute.Holder h = (Attribute.Holder) i.next();
1438             assert(h.attributes == null);
1439             
1440             long attrBits = ((h.flags & flagMask) << 32) >>> 32;
1441             
1442             h.flags -= (int)attrBits;   
1443             assert(h.flags == (char)h.flags);  
1444             assert((ctype != ATTR_CONTEXT_CODE) || h.flags == 0);
1445             if (haveLongFlags)
1446                 attrBits += (long)xxx_flags_hi.getInt() << 32;
1447             if (attrBits == 0)  continue;  
1448 
1449             int noa = 0;  
1450             long overflowBit = (attrBits & overflowMask);
1451             assert(overflowBit >= 0);
1452             attrBits -= overflowBit;
1453             if (overflowBit != 0) {
1454                 noa = xxx_attr_count.getInt();
1455             }
1456 
1457             int nfa = 0;  
1458             long bits = attrBits;
1459             for (int ai = 0; bits != 0; ai++) {
1460                 if ((bits & (1L<<ai)) == 0)  continue;
1461                 bits -= (1L<<ai);
1462                 nfa += 1;
1463             }
1464             List<Attribute> ha = new ArrayList<>(nfa + noa);
1465             h.attributes = ha;
1466             bits = attrBits;  
1467             for (int ai = 0; bits != 0; ai++) {
1468                 if ((bits & (1L<<ai)) == 0)  continue;
1469                 bits -= (1L<<ai);
1470                 totalCounts[ai] += 1;
1471                 
1472                 if (defs[ai] == null)  badAttrIndex(ai, ctype);
1473                 Attribute canonical = defs[ai].canonicalInstance();
1474                 ha.add(canonical);
1475                 nfa -= 1;
1476             }
1477             assert(nfa == 0);
1478             for (; noa > 0; noa--) {
1479                 int ai = xxx_attr_indexes.getInt();
1480                 totalCounts[ai] += 1;
1481                 
1482                 if (defs[ai] == null)  badAttrIndex(ai, ctype);
1483                 Attribute canonical = defs[ai].canonicalInstance();
1484                 ha.add(canonical);
1485             }
1486         }
1487 
1488         xxx_flags_hi.doneDisbursing();
1489         xxx_flags_lo.doneDisbursing();
1490         xxx_attr_count.doneDisbursing();
1491         xxx_attr_indexes.doneDisbursing();
1492 
1493         
1494         
1495         
1496         
1497         
1498 
1499         
1500         int callCounts = 0;
1501         for (boolean predef = true; ; predef = false) {
1502             for (int ai = 0; ai < defs.length; ai++) {
1503                 Attribute.Layout def = defs[ai];
1504                 if (def == null)  continue;  
1505                 if (predef != isPredefinedAttr(ctype, ai))
1506                     continue;  
1507                 int totalCount = totalCounts[ai];
1508                 if (totalCount == 0)
1509                     continue;  
1510                 Attribute.Layout.Element[] cbles = def.getCallables();
1511                 for (int j = 0; j < cbles.length; j++) {
1512                     assert(cbles[j].kind == Attribute.EK_CBLE);
1513                     if (cbles[j].flagTest(Attribute.EF_BACK))
1514                         callCounts += 1;
1515                 }
1516             }
1517             if (!predef)  break;
1518         }
1519         xxx_attr_calls.expectLength(callCounts);
1520         xxx_attr_calls.readFrom(in);
1521 
1522         
1523         for (boolean predef = true; ; predef = false) {
1524             for (int ai = 0; ai < defs.length; ai++) {
1525                 Attribute.Layout def = defs[ai];
1526                 if (def == null)  continue;  
1527                 if (predef != isPredefinedAttr(ctype, ai))
1528                     continue;  
1529                 int totalCount = totalCounts[ai];
1530                 Band[] ab = attrBandTable.get(def);
1531                 if (def == attrInnerClassesEmpty) {
1532                     
1533                     
1534                     
1535                     class_InnerClasses_N.expectLength(totalCount);
1536                     class_InnerClasses_N.readFrom(in);
1537                     int tupleCount = class_InnerClasses_N.getIntTotal();
1538                     class_InnerClasses_RC.expectLength(tupleCount);
1539                     class_InnerClasses_RC.readFrom(in);
1540                     class_InnerClasses_F.expectLength(tupleCount);
1541                     class_InnerClasses_F.readFrom(in);
1542                     
1543                     tupleCount -= class_InnerClasses_F.getIntCount(0);
1544                     class_InnerClasses_outer_RCN.expectLength(tupleCount);
1545                     class_InnerClasses_outer_RCN.readFrom(in);
1546                     class_InnerClasses_name_RUN.expectLength(tupleCount);
1547                     class_InnerClasses_name_RUN.readFrom(in);
1548                 } else if (totalCount == 0) {
1549                     
1550                     for (int j = 0; j < ab.length; j++) {
1551                         ab[j].doneWithUnusedBand();
1552                     }
1553                 } else {
1554                     
1555                     boolean hasCallables = def.hasCallables();
1556                     if (!hasCallables) {
1557                         readAttrBands(def.elems, totalCount, new int[0], ab);
1558                     } else {
1559                         Attribute.Layout.Element[] cbles = def.getCallables();
1560                         
1561                         
1562                         int[] forwardCounts = new int[cbles.length];
1563                         forwardCounts[0] = totalCount;
1564                         for (int j = 0; j < cbles.length; j++) {
1565                             assert(cbles[j].kind == Attribute.EK_CBLE);
1566                             int entryCount = forwardCounts[j];
1567                             forwardCounts[j] = -1;  
1568                             if (cbles[j].flagTest(Attribute.EF_BACK))
1569                                 entryCount += xxx_attr_calls.getInt();
1570                             readAttrBands(cbles[j].body, entryCount, forwardCounts, ab);
1571                         }
1572                     }
1573                 }
1574             }
1575             if (!predef)  break;
1576         }
1577         xxx_attr_calls.doneDisbursing();
1578     }
1579 
1580     void badAttrIndex(int ai, int ctype) throws IOException {
1581         throw new IOException("Unknown attribute index "+ai+" for "+
1582                                    ATTR_CONTEXT_NAME[ctype]+" attribute");
1583     }
1584 
1585     @SuppressWarnings("unchecked")
1586     void readAttrs(int ctype, Collection holders) throws IOException {
1587         
1588         Set<Attribute.Layout> sawDefs = new HashSet<>();
1589         ByteArrayOutputStream buf = new ByteArrayOutputStream();
1590         for (Iterator i = holders.iterator(); i.hasNext(); ) {
1591             final Attribute.Holder h = (Attribute.Holder) i.next();
1592             if (h.attributes == null)  continue;
1593             for (ListIterator<Attribute> j = h.attributes.listIterator(); j.hasNext(); ) {
1594                 Attribute a = j.next();
1595                 Attribute.Layout def = a.layout();
1596                 if (def.bandCount == 0) {
1597                     if (def == attrInnerClassesEmpty) {
1598                         
1599                         readLocalInnerClasses((Class) h);
1600                         continue;
1601                     }
1602                     
1603                     continue;
1604                 }
1605                 sawDefs.add(def);
1606                 boolean isCV = (ctype == ATTR_CONTEXT_FIELD && def == attrConstantValue);
1607                 if (isCV)  setConstantValueIndex((Class.Field)h);
1608                 if (verbose > 2)
1609                     Utils.log.fine("read "+a+" in "+h);
1610                 final Band[] ab = attrBandTable.get(def);
1611                 
1612                 buf.reset();
1613                 Object fixups = a.unparse(new Attribute.ValueStream() {
1614                     public int getInt(int bandIndex) {
1615                         return ((IntBand) ab[bandIndex]).getInt();
1616                     }
1617                     public Entry getRef(int bandIndex) {
1618                         return ((CPRefBand) ab[bandIndex]).getRef();
1619                     }
1620                     public int decodeBCI(int bciCode) {
1621                         Code code = (Code) h;
1622                         return code.decodeBCI(bciCode);
1623                     }
1624                 }, buf);
1625                 
1626                 j.set(a.addContent(buf.toByteArray(), fixups));
1627                 if (isCV)  setConstantValueIndex(null);  
1628             }
1629         }
1630 
1631         
1632         for (Attribute.Layout def : sawDefs) {
1633             if (def == null)  continue;  
1634             Band[] ab = attrBandTable.get(def);
1635             for (int j = 0; j < ab.length; j++) {
1636                 ab[j].doneDisbursing();
1637             }
1638         }
1639 
1640         if (ctype == ATTR_CONTEXT_CLASS) {
1641             class_InnerClasses_N.doneDisbursing();
1642             class_InnerClasses_RC.doneDisbursing();
1643             class_InnerClasses_F.doneDisbursing();
1644             class_InnerClasses_outer_RCN.doneDisbursing();
1645             class_InnerClasses_name_RUN.doneDisbursing();
1646         }
1647 
1648         MultiBand xxx_attr_bands = attrBands[ctype];
1649         for (int i = 0; i < xxx_attr_bands.size(); i++) {
1650             Band b = xxx_attr_bands.get(i);
1651             if (b instanceof MultiBand)
1652                 b.doneDisbursing();
1653         }
1654         xxx_attr_bands.doneDisbursing();
1655     }
1656 
1657     private
1658     void readAttrBands(Attribute.Layout.Element[] elems,
1659                        int count, int[] forwardCounts,
1660                        Band[] ab)
1661             throws IOException {
1662         for (int i = 0; i < elems.length; i++) {
1663             Attribute.Layout.Element e = elems[i];
1664             Band eBand = null;
1665             if (e.hasBand()) {
1666                 eBand = ab[e.bandIndex];
1667                 eBand.expectLength(count);
1668                 eBand.readFrom(in);
1669             }
1670             switch (e.kind) {
1671             case Attribute.EK_REPL:
1672                 
1673                 int repCount = ((IntBand)eBand).getIntTotal();
1674                 
1675                 readAttrBands(e.body, repCount, forwardCounts, ab);
1676                 break;
1677             case Attribute.EK_UN:
1678                 int remainingCount = count;
1679                 for (int j = 0; j < e.body.length; j++) {
1680                     int caseCount;
1681                     if (j == e.body.length-1) {
1682                         caseCount = remainingCount;
1683                     } else {
1684                         caseCount = 0;
1685                         for (int j0 = j;
1686                              (j == j0)
1687                              || (j < e.body.length
1688                                  && e.body[j].flagTest(Attribute.EF_BACK));
1689                              j++) {
1690                             caseCount += ((IntBand)eBand).getIntCount(e.body[j].value);
1691                         }
1692                         --j;  
1693                     }
1694                     remainingCount -= caseCount;
1695                     readAttrBands(e.body[j].body, caseCount, forwardCounts, ab);
1696                 }
1697                 assert(remainingCount == 0);
1698                 break;
1699             case Attribute.EK_CALL:
1700                 assert(e.body.length == 1);
1701                 assert(e.body[0].kind == Attribute.EK_CBLE);
1702                 if (!e.flagTest(Attribute.EF_BACK)) {
1703                     
1704                     
1705                     assert(forwardCounts[e.value] >= 0);
1706                     forwardCounts[e.value] += count;
1707                 }
1708                 break;
1709             case Attribute.EK_CBLE:
1710                 assert(false);
1711                 break;
1712             }
1713         }
1714     }
1715 
1716     void readByteCodes() throws IOException {
1717         
1718         
1719         
1720         
1721         
1722         
1723         
1724         
1725         
1726         
1727         
1728         
1729         
1730         
1731         
1732         
1733         
1734         
1735         
1736         
1737         
1738         
1739         
1740         
1741         
1742         
1743         bc_codes.elementCountForDebug = allCodes.length;
1744         bc_codes.setInputStreamFrom(in);
1745         readByteCodeOps();  
1746         bc_codes.doneDisbursing();
1747 
1748         
1749         Band[] operand_bands = {
1750             bc_case_value,
1751             bc_byte, bc_short,
1752             bc_local, bc_label,
1753             bc_intref, bc_floatref,
1754             bc_longref, bc_doubleref, bc_stringref,
1755             bc_classref, bc_fieldref,
1756             bc_methodref, bc_imethodref,
1757             bc_thisfield, bc_superfield,
1758             bc_thismethod, bc_supermethod,
1759             bc_initref,
1760             bc_escref, bc_escrefsize, bc_escsize
1761         };
1762         for (int i = 0; i < operand_bands.length; i++) {
1763             operand_bands[i].readFrom(in);
1764         }
1765         bc_escbyte.expectLength(bc_escsize.getIntTotal());
1766         bc_escbyte.readFrom(in);
1767 
1768         expandByteCodeOps();
1769 
1770         
1771         bc_case_count.doneDisbursing();
1772         for (int i = 0; i < operand_bands.length; i++) {
1773             operand_bands[i].doneDisbursing();
1774         }
1775         bc_escbyte.doneDisbursing();
1776         bc_bands.doneDisbursing();
1777 
1778         
1779         
1780         readAttrs(ATTR_CONTEXT_CODE, codesWithFlags);
1781         
1782         fixupCodeHandlers();
1783         
1784         code_bands.doneDisbursing();
1785         class_bands.doneDisbursing();
1786     }
1787 
1788     private void readByteCodeOps() throws IOException {
1789         
1790         byte[] buf = new byte[1<<12];
1791         
1792         List<Integer> allSwitchOps = new ArrayList<>();
1793         for (int k = 0; k < allCodes.length; k++) {
1794             Code c = allCodes[k];
1795         scanOneMethod:
1796             for (int i = 0; ; i++) {
1797                 int bc = bc_codes.getByte();
1798                 if (i + 10 > buf.length)  buf = realloc(buf);
1799                 buf[i] = (byte)bc;
1800                 boolean isWide = false;
1801                 if (bc == _wide) {
1802                     bc = bc_codes.getByte();
1803                     buf[++i] = (byte)bc;
1804                     isWide = true;
1805                 }
1806                 assert(bc == (0xFF & bc));
1807                 
1808                 switch (bc) {
1809                 case _tableswitch:
1810                 case _lookupswitch:
1811                     bc_case_count.expectMoreLength(1);
1812                     allSwitchOps.add(bc);
1813                     break;
1814                 case _iinc:
1815                     bc_local.expectMoreLength(1);
1816                     if (isWide)
1817                         bc_short.expectMoreLength(1);
1818                     else
1819                         bc_byte.expectMoreLength(1);
1820                     break;
1821                 case _sipush:
1822                     bc_short.expectMoreLength(1);
1823                     break;
1824                 case _bipush:
1825                     bc_byte.expectMoreLength(1);
1826                     break;
1827                 case _newarray:
1828                     bc_byte.expectMoreLength(1);
1829                     break;
1830                 case _multianewarray:
1831                     assert(getCPRefOpBand(bc) == bc_classref);
1832                     bc_classref.expectMoreLength(1);
1833                     bc_byte.expectMoreLength(1);
1834                     break;
1835                 case _ref_escape:
1836                     bc_escrefsize.expectMoreLength(1);
1837                     bc_escref.expectMoreLength(1);
1838                     break;
1839                 case _byte_escape:
1840                     bc_escsize.expectMoreLength(1);
1841                     
1842                     break;
1843                 default:
1844                     if (Instruction.isInvokeInitOp(bc)) {
1845                         bc_initref.expectMoreLength(1);
1846                         break;
1847                     }
1848                     if (Instruction.isSelfLinkerOp(bc)) {
1849                         CPRefBand bc_which = selfOpRefBand(bc);
1850                         bc_which.expectMoreLength(1);
1851                         break;
1852                     }
1853                     if (Instruction.isBranchOp(bc)) {
1854                         bc_label.expectMoreLength(1);
1855                         break;
1856                     }
1857                     if (Instruction.isCPRefOp(bc)) {
1858                         CPRefBand bc_which = getCPRefOpBand(bc);
1859                         bc_which.expectMoreLength(1);
1860                         assert(bc != _multianewarray);  
1861                         break;
1862                     }
1863                     if (Instruction.isLocalSlotOp(bc)) {
1864                         bc_local.expectMoreLength(1);
1865                         break;
1866                     }
1867                     break;
1868                 case _end_marker:
1869                     {
1870                         
1871                         c.bytes = realloc(buf, i);
1872                         break scanOneMethod;
1873                     }
1874                 }
1875             }
1876         }
1877 
1878         
1879         bc_case_count.readFrom(in);
1880         for (Integer i : allSwitchOps) {
1881             int bc = i.intValue();
1882             int caseCount = bc_case_count.getInt();
1883             bc_label.expectMoreLength(1+caseCount); 
1884             bc_case_value.expectMoreLength(bc == _tableswitch ? 1 : caseCount);
1885         }
1886         bc_case_count.resetForSecondPass();
1887     }
1888 
1889     private void expandByteCodeOps() throws IOException {
1890         
1891         byte[] buf = new byte[1<<12];
1892         
1893         int[] insnMap = new int[1<<12];
1894         
1895         int[] labels = new int[1<<10];
1896         
1897         Fixups fixupBuf = new Fixups();
1898 
1899         for (int k = 0; k < allCodes.length; k++) {
1900             Code code = allCodes[k];
1901             byte[] codeOps = code.bytes;
1902             code.bytes = null;  
1903 
1904             Class curClass = code.thisClass();
1905 
1906             Set<Entry> ldcRefSet = ldcRefMap.get(curClass);
1907             if (ldcRefSet == null)
1908                 ldcRefMap.put(curClass, ldcRefSet = new HashSet<>());
1909 
1910             ClassEntry thisClass  = curClass.thisClass;
1911             ClassEntry superClass = curClass.superClass;
1912             ClassEntry newClass   = null;  
1913 
1914             int pc = 0;  
1915             int numInsns = 0;
1916             int numLabels = 0;
1917             boolean hasEscs = false;
1918             fixupBuf.clear();
1919             for (int i = 0; i < codeOps.length; i++) {
1920                 int bc = Instruction.getByte(codeOps, i);
1921                 int curPC = pc;
1922                 insnMap[numInsns++] = curPC;
1923                 if (pc + 10 > buf.length)  buf = realloc(buf);
1924                 if (numInsns+10 > insnMap.length)  insnMap = realloc(insnMap);
1925                 if (numLabels+10 > labels.length)  labels = realloc(labels);
1926                 boolean isWide = false;
1927                 if (bc == _wide) {
1928                     buf[pc++] = (byte) bc;
1929                     bc = Instruction.getByte(codeOps, ++i);
1930                     isWide = true;
1931                 }
1932                 switch (bc) {
1933                 case _tableswitch: 
1934                 case _lookupswitch: 
1935                     {
1936                         int caseCount = bc_case_count.getInt();
1937                         while ((pc + 30 + caseCount*8) > buf.length)
1938                             buf = realloc(buf);
1939                         buf[pc++] = (byte) bc;
1940                         
1941                         Arrays.fill(buf, pc, pc+30, (byte)0);
1942                         Instruction.Switch isw = (Instruction.Switch)
1943                             Instruction.at(buf, curPC);
1944                         
1945                         isw.setCaseCount(caseCount);
1946                         if (bc == _tableswitch) {
1947                             isw.setCaseValue(0, bc_case_value.getInt());
1948                         } else {
1949                             for (int j = 0; j < caseCount; j++) {
1950                                 isw.setCaseValue(j, bc_case_value.getInt());
1951                             }
1952                         }
1953                         
1954                         labels[numLabels++] = curPC;
1955                         pc = isw.getNextPC();
1956                         continue;
1957                     }
1958                 case _iinc:
1959                     {
1960                         buf[pc++] = (byte) bc;
1961                         int local = bc_local.getInt();
1962                         int delta;
1963                         if (isWide) {
1964                             delta = bc_short.getInt();
1965                             Instruction.setShort(buf, pc, local); pc += 2;
1966                             Instruction.setShort(buf, pc, delta); pc += 2;
1967                         } else {
1968                             delta = (byte) bc_byte.getByte();
1969                             buf[pc++] = (byte)local;
1970                             buf[pc++] = (byte)delta;
1971                         }
1972                         continue;
1973                     }
1974                 case _sipush:
1975                     {
1976                         int val = bc_short.getInt();
1977                         buf[pc++] = (byte) bc;
1978                         Instruction.setShort(buf, pc, val); pc += 2;
1979                         continue;
1980                     }
1981                 case _bipush:
1982                 case _newarray:
1983                     {
1984                         int val = bc_byte.getByte();
1985                         buf[pc++] = (byte) bc;
1986                         buf[pc++] = (byte) val;
1987                         continue;
1988                     }
1989                 case _ref_escape:
1990                     {
1991                         
1992                         hasEscs = true;
1993                         int size = bc_escrefsize.getInt();
1994                         Entry ref = bc_escref.getRef();
1995                         if (size == 1)  ldcRefSet.add(ref);
1996                         int fmt;
1997                         switch (size) {
1998                         case 1: fmt = Fixups.U1_FORMAT; break;
1999                         case 2: fmt = Fixups.U2_FORMAT; break;
2000                         default: assert(false); fmt = 0;
2001                         }
2002                         fixupBuf.add(pc, fmt, ref);
2003                         buf[pc+0] = buf[pc+1] = 0;
2004                         pc += size;
2005                     }
2006                     continue;
2007                 case _byte_escape:
2008                     {
2009                         
2010                         hasEscs = true;
2011                         int size = bc_escsize.getInt();
2012                         while ((pc + size) > buf.length)
2013                             buf = realloc(buf);
2014                         while (size-- > 0) {
2015                             buf[pc++] = (byte) bc_escbyte.getByte();
2016                         }
2017                     }
2018                     continue;
2019                 default:
2020                     if (Instruction.isInvokeInitOp(bc)) {
2021                         int idx = (bc - _invokeinit_op);
2022                         int origBC = _invokespecial;
2023                         ClassEntry classRef;
2024                         switch (idx) {
2025                         case _invokeinit_self_option:
2026                             classRef = thisClass; break;
2027                         case _invokeinit_super_option:
2028                             classRef = superClass; break;
2029                         default:
2030                             assert(idx == _invokeinit_new_option);
2031                             classRef = newClass; break;
2032                         }
2033                         buf[pc++] = (byte) origBC;
2034                         int coding = bc_initref.getInt();
2035                         
2036                         MemberEntry ref = pkg.cp.getOverloadingForIndex(CONSTANT_Methodref, classRef, "<init>", coding);
2037                         fixupBuf.add(pc, Fixups.U2_FORMAT, ref);
2038                         buf[pc+0] = buf[pc+1] = 0;
2039                         pc += 2;
2040                         assert(Instruction.opLength(origBC) == (pc - curPC));
2041                         continue;
2042                     }
2043                     if (Instruction.isSelfLinkerOp(bc)) {
2044                         int idx = (bc - _self_linker_op);
2045                         boolean isSuper = (idx >= _self_linker_super_flag);
2046                         if (isSuper)  idx -= _self_linker_super_flag;
2047                         boolean isAload = (idx >= _self_linker_aload_flag);
2048                         if (isAload)  idx -= _self_linker_aload_flag;
2049                         int origBC = _first_linker_op + idx;
2050                         boolean isField = Instruction.isFieldOp(origBC);
2051                         CPRefBand bc_which;
2052                         ClassEntry which_cls  = isSuper ? superClass : thisClass;
2053                         Index which_ix;
2054                         if (isField) {
2055                             bc_which = isSuper ? bc_superfield  : bc_thisfield;
2056                             which_ix = pkg.cp.getMemberIndex(CONSTANT_Fieldref, which_cls);
2057                         } else {
2058                             bc_which = isSuper ? bc_supermethod : bc_thismethod;
2059                             which_ix = pkg.cp.getMemberIndex(CONSTANT_Methodref, which_cls);
2060                         }
2061                         assert(bc_which == selfOpRefBand(bc));
2062                         MemberEntry ref = (MemberEntry) bc_which.getRef(which_ix);
2063                         if (isAload) {
2064                             buf[pc++] = (byte) _aload_0;
2065                             curPC = pc;
2066                             
2067                             insnMap[numInsns++] = curPC;
2068                         }
2069                         buf[pc++] = (byte) origBC;
2070                         fixupBuf.add(pc, Fixups.U2_FORMAT, ref);
2071                         buf[pc+0] = buf[pc+1] = 0;
2072                         pc += 2;
2073                         assert(Instruction.opLength(origBC) == (pc - curPC));
2074                         continue;
2075                     }
2076                     if (Instruction.isBranchOp(bc)) {
2077                         buf[pc++] = (byte) bc;
2078                         assert(!isWide);  
2079                         int nextPC = curPC + Instruction.opLength(bc);
2080                         
2081                         labels[numLabels++] = curPC;
2082                         
2083                         while (pc < nextPC)  buf[pc++] = 0;
2084                         continue;
2085                     }
2086                     if (Instruction.isCPRefOp(bc)) {
2087                         CPRefBand bc_which = getCPRefOpBand(bc);
2088                         Entry ref = bc_which.getRef();
2089                         if (ref == null) {
2090                             if (bc_which == bc_classref) {
2091                                 
2092                                 ref = thisClass;
2093                             } else {
2094                                 assert(false);
2095                             }
2096                         }
2097                         int origBC = bc;
2098                         int size = 2;
2099                         switch (bc) {
2100                         case _ildc:
2101                         case _cldc:
2102                         case _fldc:
2103                         case _aldc:
2104                             origBC = _ldc;
2105                             size = 1;
2106                             ldcRefSet.add(ref);
2107                             break;
2108                         case _ildc_w:
2109                         case _cldc_w:
2110                         case _fldc_w:
2111                         case _aldc_w:
2112                             origBC = _ldc_w;
2113                             break;
2114                         case _lldc2_w:
2115                         case _dldc2_w:
2116                             origBC = _ldc2_w;
2117                             break;
2118                         case _new:
2119                             newClass = (ClassEntry) ref;
2120                             break;
2121                         }
2122                         buf[pc++] = (byte) origBC;
2123                         int fmt;
2124                         switch (size) {
2125                         case 1: fmt = Fixups.U1_FORMAT; break;
2126                         case 2: fmt = Fixups.U2_FORMAT; break;
2127                         default: assert(false); fmt = 0;
2128                         }
2129                         fixupBuf.add(pc, fmt, ref);
2130                         buf[pc+0] = buf[pc+1] = 0;
2131                         pc += size;
2132                         if (origBC == _multianewarray) {
2133                             
2134                             int val = bc_byte.getByte();
2135                             buf[pc++] = (byte) val;
2136                         } else if (origBC == _invokeinterface) {
2137                             int argSize = ((MemberEntry)ref).descRef.typeRef.computeSize(true);
2138                             buf[pc++] = (byte)( 1 + argSize );
2139                             buf[pc++] = 0;
2140                         }
2141                         assert(Instruction.opLength(origBC) == (pc - curPC));
2142                         continue;
2143                     }
2144                     if (Instruction.isLocalSlotOp(bc)) {
2145                         buf[pc++] = (byte) bc;
2146                         int local = bc_local.getInt();
2147                         if (isWide) {
2148                             Instruction.setShort(buf, pc, local);
2149                             pc += 2;
2150                             if (bc == _iinc) {
2151                                 int iVal = bc_short.getInt();
2152                                 Instruction.setShort(buf, pc, iVal);
2153                                 pc += 2;
2154                             }
2155                         } else {
2156                             Instruction.setByte(buf, pc, local);
2157                             pc += 1;
2158                             if (bc == _iinc) {
2159                                 int iVal = bc_byte.getByte();
2160                                 Instruction.setByte(buf, pc, iVal);
2161                                 pc += 1;
2162                             }
2163                         }
2164                         assert(Instruction.opLength(bc) == (pc - curPC));
2165                         continue;
2166                     }
2167                     
2168                     if (bc >= _bytecode_limit)
2169                         Utils.log.warning("unrecognized bytescode "+bc
2170                                             +" "+Instruction.byteName(bc));
2171                     assert(bc < _bytecode_limit);
2172                     buf[pc++] = (byte) bc;
2173                     assert(Instruction.opLength(bc) == (pc - curPC));
2174                     continue;
2175                 }
2176             }
2177             
2178             code.setBytes(realloc(buf, pc));
2179             code.setInstructionMap(insnMap, numInsns);
2180             
2181             Instruction ibr = null;  
2182             for (int i = 0; i < numLabels; i++) {
2183                 int curPC = labels[i];
2184                 
2185                 ibr = Instruction.at(code.bytes, curPC, ibr);
2186                 if (ibr instanceof Instruction.Switch) {
2187                     Instruction.Switch isw = (Instruction.Switch) ibr;
2188                     isw.setDefaultLabel(getLabel(bc_label, code, curPC));
2189                     int caseCount = isw.getCaseCount();
2190                     for (int j = 0; j < caseCount; j++) {
2191                         isw.setCaseLabel(j, getLabel(bc_label, code, curPC));
2192                     }
2193                 } else {
2194                     ibr.setBranchLabel(getLabel(bc_label, code, curPC));
2195                 }
2196             }
2197             if (fixupBuf.size() > 0) {
2198                 if (verbose > 2)
2199                     Utils.log.fine("Fixups in code: "+fixupBuf);
2200                 code.addFixups(fixupBuf);
2201             }
2202         }
2203     }
2204 }